﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;

using Radar.Utils;
using System.Xml.Serialization;
using Jage.Utils;
using System.Runtime.Serialization;
using System.Security.Permissions;
using System.Xml.Schema;

namespace Radar
{
    public class MapDefinition
        : SaveObject<MapDefinition>
    {

        public MapDefinition()
        {
            Terrain = new TerrainDefinition();
            Grid = new GridDefinition();
            NavMesh = new NavMeshDefinition();
        }

        [XmlAttribute()]
        public string Name { get; set; }

        public string Description { get; set; }

        [XmlAttribute()]
        public int Width { get; set; }

        [XmlAttribute()]
        public int Height { get; set; }

        public TerrainDefinition Terrain { get; set; }

        public GridDefinition Grid { get; set; }

        public NavMeshDefinition NavMesh { get; set; }

    }

    public class GridDefinition
    {
        [XmlAttribute()]
        public int Width { get; set; }

        [XmlAttribute()]
        public int Height { get; set; }
    }

    public class NavMeshDefinition
    {

        public NavMeshDefinition()
        {
            Zones = new List<NavZoneDefinition>();
        }

        public List<NavZoneDefinition> Zones;

    }

    public class NavZoneDefinition
    {

        public NavZoneDefinition()
        {
        }

        public NavZoneDefinition(int left, int top, int right, int bottom)
            : this()
        {
            Left = left;
            Top = top;
            Right = right;
            Bottom = bottom;
        }

        [XmlAttribute()]
        public int Left { get; set; }

        [XmlAttribute()]
        public int Top { get; set; }

        [XmlAttribute()]
        public int Right { get; set; }

        [XmlAttribute()]
        public int Bottom { get; set; }

    }

    [Serializable()]
    public class TerrainDefinition
    {

        private byte[,] _terrain;

        public TerrainDefinition()
        {
            _terrain = new byte[0, 0];
        }

        public byte this[int x, int y]
        {
            get
            {
                return _terrain[x, y];
            }
            set
            {
                _terrain[x, y] = value;
            }
        }

        public void Init(int width, int height)
        {
            _terrain = new Byte[width, height];
        }

        private string GetTilesAsString()
        {
            StringBuilder sb = new StringBuilder();
            for (int y = 0; y < _terrain.GetLength(1); y++)
            {
                for (int x = 0; x < _terrain.GetLength(0); x++)
                {
                    sb.Append(_terrain[x, y].ToString().PadLeft(3, '0') + ",");
                }
                sb.Remove(sb.Length - 1, 1);
                sb.AppendLine();
            }
            return sb.ToString().TrimEnd();
        }

        private void SetTilesFromString(string value)
        {
            int y = 0;
            string[] rows = value.Split(new Char[] {'\n'}, StringSplitOptions.None);
            if (rows.Length > 0 && rows[0].Length > 0)
            {
                Init(rows[0].Length / 3, rows.Length);
                foreach (string row in rows)
                {
                    int x = 0;
                    foreach (string tile in row.Trim().Split(','))
                    {
                        byte v = 0;
                        if (byte.TryParse(tile, out v))
                        {
                            _terrain[x, y] = v;
                        }
                        else
                        {
                            throw new RadarException("Error in map file: Terrain.Tiles data contains non-bytes.");
                        }
                    }
                    y++;
                }
            }
        }

        public string Tiles { get { return GetTilesAsString(); } set { SetTilesFromString(value); } }

    }

}
